#include "core/syscall.h"
#include "core/task.h"
#include "tools/log.h"
#include "fs/fs.h"
#include "core/memory.h"

typedef int (* sys_handler_t)(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3);

void sys_print_msg(char * fmt, int arg)
{
    log_printf(fmt, arg);
}

static const sys_handler_t syscall_table[] = {
    [SYS_SLEEP_ID] = (sys_handler_t)sys_sleep,
    [SYS_GET_PRESENT_ID] = (sys_handler_t)sys_getpid,
    [SYS_PRINT_MSG_ID] = (sys_handler_t)sys_print_msg,
    [SYS_FORK_ID] = (sys_handler_t)sys_fork,
    [SYS_YIELD_ID] = (sys_handler_t)sys_yield,
    [SYS_EXECVE_ID] = (sys_handler_t)sys_execve,
    [SYS_EXIT_ID] = (sys_handler_t)sys_exit,
    [SYS_WAIT_ID] = (sys_handler_t)sys_wait,

    [SYS_OPEN_ID] = (sys_handler_t)sys_open,
    [SYS_READ_ID] = (sys_handler_t)sys_read,
    [SYS_WRITE_ID] = (sys_handler_t)sys_write,
    [SYS_CLOSE_ID] = (sys_handler_t)sys_close,
    [SYS_LSEEK_ID] = (sys_handler_t)sys_lseek,

    [SYS_ISATTY_ID] = (sys_handler_t)sys_isatty,
    [SYS_FSTAT_ID] = (sys_handler_t)sys_fstat,
    [SYS_SBRK_ID] = (sys_handler_t)sys_sbrk,
    [SYS_DUP_ID]  = (sys_handler_t)sys_dup, 
    [SYS_IOCTL_ID] = (sys_handler_t)sys_ioctl,

    [SYS_OPENDIR_ID] = (sys_handler_t)sys_opendir,
    [SYS_READDIR_ID] = (sys_handler_t)sys_readdir,
    [SYS_CLOSEDIR_ID] = (sys_handler_t)sys_closedir,
    [SYS_UNLINK_ID] = (sys_handler_t)sys_unlink,
};

void do_handler_syscall(syscall_frame_t * syscall_frame)
{
    if(syscall_frame->func_id < sizeof(syscall_table) / sizeof(syscall_table[0]))
    {
        sys_handler_t sys_handler = syscall_table[syscall_frame->func_id];
        if(sys_handler)
        {
            int ret = sys_handler(syscall_frame->arg0, 
                                  syscall_frame->arg1, 
                                  syscall_frame->arg2, 
                                  syscall_frame->arg3);
            // eax用于汇编中的函数返回值存储
            // 此处修改了exception_handler_syscall中栈中eax的值
            // 在出栈的时候，会将ret写入eax
            syscall_frame->eax = ret;
            return;
        }
    }

    task_t * curr_task = curr_task_get();
    log_printf("task: %s, Unknown syscall: %d", curr_task->name, syscall_frame->func_id);
}

